package com.xyzq.simpson.apm.web.controller;

import com.xyzq.simpson.apm.web.enums.TypeEnum;
import com.xyzq.simpson.apm.web.utils.DurationUtil;
import com.xyzq.simpson.apm.web.utils.ResponseEntity;
import com.xyzq.simpson.hibbert.storage.es.brief.ResponseBrief;
import com.xyzq.simpson.hibbert.storage.es.brief.TraceBrief;
import com.xyzq.simpson.hibbert.storage.es.constrant.CodeState;
import com.xyzq.simpson.hibbert.storage.es.constrant.QueryOrder;
import com.xyzq.simpson.hibbert.storage.es.dao.ITraceQueryDAO;
import com.xyzq.simpson.hibbert.storage.es.manager.EsQueryManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;

@Controller
@RequestMapping("/apm/api/trace")
public class TraceController {
    protected Logger logger = LoggerFactory.getLogger(TraceController.class);

    @RequestMapping(value = "/traceList", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity traceList(@RequestBody Map<String, Object> json) throws Exception {
        ITraceQueryDAO traceQueryEsDAO = EsQueryManager.instance().getService(ITraceQueryDAO.class);
        long startTimeStamp = DurationUtil.getStartTimeStampFromTraceDuration(json);
        long endTimeStamp = DurationUtil.getEndTimeStampFromTraceDuration(json);
        Map<String, Object> paging = (Map<String, Object>)json.get("paging");
        int page = Integer.valueOf(""+paging.get("pageNum"));
        int size = Integer.valueOf(""+paging.get("pageSize"));
        int traceType = json.get("traceType") == null ? 0 : Integer.valueOf(""+json.get("traceType"));
        int codeState = json.get("traceState") == null ? 0 : Integer.valueOf(""+json.get("traceState")); //
        String queryOrder = json.get("queryOrder") == null ? "" : String.valueOf(json.get("queryOrder"));
        String serialNo = json.get("traceId") == null ? "" : String.valueOf(json.get("traceId"));
        String project = json.get("serviceId") == null || "ALL".equalsIgnoreCase(""+json.get("serviceId")) ? "" : String.valueOf(json.get("serviceId"));
        String ip = json.get("serviceInstanceId") == null || "ALL".equalsIgnoreCase(""+json.get("serviceInstanceId")) ? "" : String.valueOf(json.get("serviceInstanceId"));
        String match = json.get("match") == null ? "" : String.valueOf(json.get("match")); //
        long minDuration = json.get("minTraceDuration") == null ? 0 : Long.valueOf(""+json.get("minTraceDuration"));
        long maxDuration = json.get("maxTraceDuration") == null ? 0 : Long.valueOf(""+json.get("maxTraceDuration"));
        int from = (page - 1) * size;
        ResponseBrief responseBrief = null;
        if(StringUtils.isNotBlank(serialNo)) { //有流水号，使用流水号查询接口
            responseBrief = traceQueryEsDAO.queryTracesBySerialNo2(
                    startTimeStamp, endTimeStamp, serialNo, from, size, QueryOrder.of(queryOrder));
        } else if(TypeEnum.ALL.getCode() == traceType) {
            responseBrief = traceQueryEsDAO.queryTraces(startTimeStamp, endTimeStamp, project, ip, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
        } else if(TypeEnum.HTTP_EXECUTE.getCode() == traceType) {
            String uri = json.get("input_uri") == null ? "" : String.valueOf(json.get("input_uri"));
            responseBrief = traceQueryEsDAO.queryHttpExecuteTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    uri, project, ip, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("http-execute");
            });
        } else if(TypeEnum.HTTP_INVOKE.getCode() == traceType) {
            String url = json.get("input_url") == null ? "" : String.valueOf(json.get("input_url"));
            responseBrief = traceQueryEsDAO.queryHttpInvokeTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    url, project, ip, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("http-invoke");
            });
        } else if(TypeEnum.RPC_EXECUTE.getCode() == traceType) {
            String serviceName = json.get("input_service") == null ? "" : String.valueOf(json.get("input_service"));
            String methodName = json.get("input_method") == null ? "" : String.valueOf(json.get("input_method"));
            responseBrief = traceQueryEsDAO.queryRpcExecuteTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    project, ip, serviceName, methodName, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("rpc-execute");
            });
        } else if(TypeEnum.RPC_INVOKE.getCode() == traceType) {
            String serviceName = json.get("input_service") == null ? "" : String.valueOf(json.get("input_service"));
            String methodName = json.get("input_method") == null ? "" : String.valueOf(json.get("input_method"));
            responseBrief = traceQueryEsDAO.queryRpcInvokeTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    project, ip, serviceName, methodName, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("rpc-invoke");
            });
        } else if(TypeEnum.CACHE.getCode() == traceType) {
            String namespace = json.get("input_namespace") == null ? "" : String.valueOf(json.get("input_namespace"));
            String category = json.get("input_category") == null ? "" : String.valueOf(json.get("input_category"));
            responseBrief = traceQueryEsDAO.queryCacheTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    project, ip, category, namespace, null, null, null, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("cache");
            });
        } else if(TypeEnum.SQL.getCode() == traceType) {
            String mapper = json.get("input_mapper") == null ? "" : String.valueOf(json.get("input_mapper"));
            responseBrief = traceQueryEsDAO.querySqlTraces(startTimeStamp, endTimeStamp, minDuration, maxDuration,
                    project, ip, mapper, serialNo, CodeState.of(codeState),
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("sql");
            });
        } else if(TypeEnum.LOG.getCode() == traceType) {
            responseBrief = traceQueryEsDAO.queryLogTraces(startTimeStamp, endTimeStamp,
                    project, ip, null, serialNo,
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("log");
            });
        } else if(TypeEnum.EXCEPTION.getCode() == traceType) {
            responseBrief = traceQueryEsDAO.queryExceptionTraces(startTimeStamp, endTimeStamp,
                    project, ip, null, serialNo,
                    match, from, size, QueryOrder.of(queryOrder));
            responseBrief.getTraces().forEach(x -> {
                TraceBrief t = (TraceBrief)x;
                t.setType("exception");
            });
        }
        return new ResponseEntity().success(responseBrief);
    }
}